/**
 * Created by LiYang on 16-9-27 下午2:07.
 *
 */
package com.example.db.mapper;

import android.database.Cursor;
import android.util.Log;

import com.example.db.DBSerializable;
import com.example.db.common.EntityHashMap;
import com.example.db.exception.InstanceClassException;
import com.example.db.exception.InvokeFieldException;
import com.example.db.exception.InvokeMethodException;
import com.example.db.utils.BeanUtil;
import com.example.db.utils.JdbcUtil;
import com.example.db.utils.ObjectUtil;

import org.springframework.core.convert.TypeDescriptor;

import java.sql.SQLException;

/**
 * @author qul
 * @since LVGG1.1
 */
public class ModelMapperHandler<T extends DBSerializable> extends RowMapperHandler<T> {

    private String TAG = "modelMapperHandler";
    private Class<T> superClass;

    public ModelMapperHandler(Class<T> superClass) {
        this.superClass = superClass;
    }

    @Override
    public T rowMapper(Cursor cursor) throws SQLException {
        if (superClass == null) {
            return null;
        }
        if (superClass.isAssignableFrom(EntityHashMap.class)) {
            return createModelMap(cursor);
        }
        return createModelBean(cursor);
    }

    @SuppressWarnings("unchecked")
    private T createModelMap(Cursor cursor) throws SQLException {
        EntityHashMap mm = new EntityHashMap();
        int cc = cursor.getColumnCount();
        for (int i = 0; i < cc; i++) {
            String cn = getMapName(cursor, i);
            Object value = JdbcUtil.getColumnValue(cursor, i);
            if ("id".equals(cn)) {
                mm.setId((Long) value);
            }

            mm.put(cn, value);
        }
        return (T) mm;
    }

    @SuppressWarnings("unchecked")
    private T createModelBean(Cursor cursor) throws SQLException {
        T obj;
        try {
            obj = BeanUtil.instanceClass(superClass);
        } catch (InstanceClassException e) {
            Log.e(TAG, "", e);
            return null;
        } catch (InvokeMethodException e) {
            Log.e(TAG, "", e);
            return null;
        }
        int cc = cursor.getColumnCount();
        for (int i = 0; i < cc; i++) {
            String fn = getFieldName(cursor, i);
            Object value = JdbcUtil.getColumnValue(cursor, i);
            setBeanValue(obj, fn, value);
        }
        return obj;
    }

    @SuppressWarnings("unchecked")
    private void setBeanValue(Object obj, String fn, Object value) {
        try {
            TypeDescriptor descriptor = BeanUtil.getFieldDescriptor(superClass, fn);
            Object val = ObjectUtil.toObject(descriptor, value);
            BeanUtil.setFieldValue(obj, fn, val);
        } catch (InvokeFieldException e) {
            Log.d(TAG, "", e);
        }
    }
}
